<template>
  <div class="upload-box">
    <div
      :class="['upload', drag ? 'no-border' : '']"
      class="upload-wrapper"
      @click="openFileSelector"
    >
      <template v-if="modelValue">
        <img :src="modelValue" class="upload-image" />
        <div class="upload-handle" @click.stop>
          <div class="handle-icon" @click="imagePreview(modelValue)">
            <Icon icon="ep:zoom-in" />
            <span v-if="showBtnText">{{ t('action.detail') }}</span>
          </div>
          <div class="handle-icon" @click="openFileSelector">
            <Icon icon="ep:folder" />
            <span v-if="showBtnText">选择文件</span>
          </div>
          <div v-if="showDelete && !disabled" class="handle-icon" @click="deleteImg">
            <Icon icon="ep:delete" />
            <span v-if="showBtnText">{{ t('action.del') }}</span>
          </div>
        </div>
      </template>
      <template v-else>
        <div class="upload-empty" @click.stop="openFileSelector">
          <slot name="empty">
            <Icon icon="ep:plus" />
            <!-- <span>请上传图片</span> -->
          </slot>
        </div>
      </template>
    </div>
    <div class="el-upload__tip">
      <slot name="tip"></slot>
    </div>

    <!-- 文件选择弹窗 -->
    <el-dialog
      v-model="fileSelectorVisible"
      title="图片相册"
      width="60%"
      :close-on-click-modal="false"
      class="file-selector-dialog"
    >
      <div class="file-selector-container">
        <!-- 左侧分组列表 -->
        <div class="classify-sidebar">
          <div class="classify-list">
            <div
              class="classify-item"
              :class="{ active: currentClassifyId === null }"
              @click="selectClassify(null, '全部')"
            >
              <Icon icon="ep:folder" />
              <span>全部</span>
            </div>

            <div
              v-for="classify in classifyList"
              :key="classify.id"
              class="classify-item"
              :class="{ active: currentClassifyId === classify.id }"
              @click="selectClassify(classify.id, classify.name)"
            >
              <Icon icon="ep:folder" />
              <span>{{ classify.name }}</span>
              <div class="classify-actions">
                <el-button
                  type="text"
                  size="small"
                  :icon="Edit"
                  @click.stop="editClassify(classify)"
                />
                <el-dropdown @click.stop trigger="click">
                  <el-button type="text" size="small" :icon="MoreFilled" />
                  <template #dropdown>
                    <el-dropdown-menu>
                      <el-dropdown-item @click="editClassify(classify)">
                        <Icon icon="ep:edit" />
                        编辑
                      </el-dropdown-item>
                      <el-dropdown-item @click="deleteClassify(classify.id)">
                        <Icon icon="ep:delete" />
                        删除
                      </el-dropdown-item>
                    </el-dropdown-menu>
                  </template>
                </el-dropdown>
              </div>
            </div>
          </div>

          <div class="add-classify-btn">
            <el-button
              type="primary"
              size="small"
              :icon="Plus"
              @click="showAddClassifyDialog"
              style="height: 100%; width: 90%"
            >
              添加相册
            </el-button>
          </div>
        </div>

        <!-- 右侧文件列表 -->
        <div class="file-content-section">
          <!-- 顶部工具栏 -->
          <div class="toolbar">
            <div class="toolbar-left">
              <el-upload
                :accept="fileType.join(',')"
                :action="uploadUrl"
                :before-upload="beforeUpload"
                :http-request="httpRequestForDialog"
                :multiple="false"
                :on-error="uploadError"
                :on-success="uploadSuccessForDialog"
                :show-file-list="false"
              >
                <el-button type="primary" :icon="Upload"> 上传图片 </el-button>
              </el-upload>
            </div>
            <!--            <div class="toolbar-right">-->
            <!--              <span>排序：</span>-->
            <!--              <el-select v-model="sortType" size="small" style="width: 120px">-->
            <!--                <el-option label="时间从后到前" value="createTime_desc" />-->
            <!--                <el-option label="时间从前到后" value="createTime_asc" />-->
            <!--                <el-option label="文件名A-Z" value="name_asc" />-->
            <!--                <el-option label="文件名Z-A" value="name_desc" />-->
            <!--              </el-select>-->
            <!--            </div>-->
          </div>

          <!-- 文件网格列表 -->
          <div v-loading="fileListLoading" class="file-grid-container">
            <div class="file-grid">
              <div
                v-for="file in fileList"
                :key="file.id"
                class="file-item"
                :class="{ selected: selectedFile?.id === file.id }"
                @click="selectFile(file)"
              >
                <div class="file-preview">
                  <el-image
                    v-if="file.type && file.type.includes('image')"
                    :src="file.url"
                    fit="cover"
                    class="file-image"
                  />
                  <div v-else class="file-icon">
                    <Icon icon="ep:document" class="text-4xl text-gray-400" />
                  </div>

                  <!-- 选中标识 -->
                  <div v-if="selectedFile?.id === file.id" class="selected-mark">
                    <Icon icon="ep:check" />
                  </div>

                  <!-- 删除按钮 -->
                  <div class="file-actions" @click.stop>
                    <el-button
                      type="danger"
                      size="small"
                      :icon="Delete"
                      circle
                      @click="deleteFileFromList(file.id)"
                    />
                  </div>
                </div>

                <div class="file-name" :title="file.name">{{ file.name }}</div>
              </div>
            </div>

            <!-- 空状态 -->
            <el-empty v-if="!fileListLoading && fileList.length === 0" description="暂无文件" />
          </div>

          <!-- 底部分页和统计 -->
          <div class="bottom-bar">
            <div class="file-stats">
              第{{ (queryParams.pageNo - 1) * queryParams.pageSize + 1 }}-{{
                Math.min(queryParams.pageNo * queryParams.pageSize, total)
              }}
              条 / 共计 {{ total }} 条
            </div>
            <el-pagination
              v-model:current-page="queryParams.pageNo"
              v-model:page-size="queryParams.pageSize"
              :total="total"
              :page-sizes="[15, 30, 60, 120]"
              layout="prev, pager, next"
              @size-change="getFileList"
              @current-change="getFileList"
              small
            />
          </div>
        </div>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="fileSelectorVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmSelection" :disabled="!selectedFile">
            确定选择
          </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 添加/编辑分组弹窗 -->
    <el-dialog
      v-model="classifyDialogVisible"
      :title="isEditClassify ? '编辑分组' : '添加分组'"
      width="400px"
      :close-on-click-modal="false"
    >
      <el-form :model="classifyForm" label-width="80px" ref="classifyFormRef">
        <el-form-item label="分组名称" required>
          <el-input v-model="classifyForm.name" placeholder="请输入分组名称" />
        </el-form-item>
      </el-form>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="classifyDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmClassifyAction">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import type { UploadProps } from 'element-plus'
import { Upload, Delete, Plus, Edit, MoreFilled } from '@element-plus/icons-vue'

import { generateUUID } from '@/utils'
import { propTypes } from '@/utils/propTypes'
import { createImageViewer } from '@/components/ImageViewer'
import { useUpload } from '@/components/UploadFile/src/useUpload'
import * as FileApi from '@/api/infra/file'
import { FileClassifyApi } from '@/api/infra/fileClassify'
import { ElMessageBox } from 'element-plus'

defineOptions({ name: 'UploadImg' })

type FileTypes =
  | 'image/apng'
  | 'image/bmp'
  | 'image/gif'
  | 'image/jpeg'
  | 'image/pjpeg'
  | 'image/png'
  | 'image/svg+xml'
  | 'image/tiff'
  | 'image/webp'
  | 'image/x-icon'

// 接受父组件参数
const props = defineProps({
  modelValue: propTypes.string.def(''),
  drag: propTypes.bool.def(true), // 是否支持拖拽上传 ==> 非必传（默认为 true）
  disabled: propTypes.bool.def(false), // 是否禁用上传组件 ==> 非必传（默认为 false）
  fileSize: propTypes.number.def(5), // 图片大小限制 ==> 非必传（默认为 5M）
  fileType: propTypes.array.def(['image/jpeg', 'image/png', 'image/gif']), // 图片类型限制 ==> 非必传（默认为 ["image/jpeg", "image/png", "image/gif"]）
  height: propTypes.string.def('150px'), // 组件高度 ==> 非必传（默认为 150px）
  width: propTypes.string.def('150px'), // 组件宽度 ==> 非必传（默认为 150px）
  borderradius: propTypes.string.def('8px'), // 组件边框圆角 ==> 非必传（默认为 8px）
  showDelete: propTypes.bool.def(true), // 是否显示删除按钮
  showBtnText: propTypes.bool.def(true), // 是否显示按钮文字
  directory: propTypes.string.def(undefined) // 上传目录 ==> 非必传（默认为 undefined）
})
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
// 生成组件唯一id
const uuid = ref('id-' + generateUUID())

// 文件选择弹窗相关
const fileSelectorVisible = ref(false)
const fileListLoading = ref(false)
const fileList = ref([])
const total = ref(0)
const selectedFile = ref(null)

// 分组相关
const classifyList = ref([])
const currentClassifyId = ref(null)
const currentClassifyName = ref('全部')
const classifyDialogVisible = ref(false)
const isEditClassify = ref(false)
const classifyForm = ref({ id: null, name: '' })
const classifyFormRef = ref()

// 排序
const sortType = ref('createTime_desc')

// 查询参数
const queryParams = ref({
  pageNo: 1,
  pageSize: 15,
  classifyId: undefined
})

// 查看图片
const imagePreview = (imgUrl: string) => {
  createImageViewer({
    zIndex: 9999999,
    urlList: [imgUrl]
  })
}

const emit = defineEmits(['update:modelValue'])

const deleteImg = () => {
  emit('update:modelValue', '')
}

const { uploadUrl, httpRequest } = useUpload(props.directory)

const beforeUpload: UploadProps['beforeUpload'] = (rawFile) => {
  const imgSize = rawFile.size / 1024 / 1024 < props.fileSize
  const imgType = props.fileType
  if (!imgType.includes(rawFile.type as FileTypes))
    message.notifyWarning('上传图片不符合所需的格式！')
  if (!imgSize) message.notifyWarning(`上传图片大小不能超过 ${props.fileSize}M！`)
  return imgType.includes(rawFile.type as FileTypes) && imgSize
}

// 图片上传错误提示
const uploadError = () => {
  message.notifyError('图片上传失败，请您重新上传！')
}

// 打开文件选择器
const openFileSelector = () => {
  fileSelectorVisible.value = true
  getClassifyList()
  getFileList()
}

// 获取分组列表
const getClassifyList = async () => {
  try {
    const data = await FileClassifyApi.getFileClassifySimpleList()
    classifyList.value = data || []
  } catch (error) {
    console.error('获取分组列表失败:', error)
  }
}

// 获取文件列表
const getFileList = async () => {
  fileListLoading.value = true
  try {
    const params = {
      ...queryParams.value,
      classifyId: currentClassifyId.value
    }
    const data = await FileApi.getFilePage(params)
    fileList.value = data.list || []
    total.value = data.total || 0
  } catch (error) {
    console.error('获取文件列表失败:', error)
  } finally {
    fileListLoading.value = false
  }
}

// 选择分组
const selectClassify = (classifyId, classifyName) => {
  currentClassifyId.value = classifyId
  currentClassifyName.value = classifyName
  queryParams.value.pageNo = 1
  getFileList()
}

// 选择文件
const selectFile = (file) => {
  selectedFile.value = file
}

// 确认选择
const confirmSelection = () => {
  if (selectedFile.value) {
    emit('update:modelValue', selectedFile.value.url)
    fileSelectorVisible.value = false
    selectedFile.value = null
  }
}

// 格式化文件大小
const formatFileSize = (size) => {
  if (!size) return '0 B'
  const units = ['B', 'KB', 'MB', 'GB']
  let index = 0
  while (size >= 1024 && index < units.length - 1) {
    size /= 1024
    index++
  }
  return `${size.toFixed(1)} ${units[index]}`
}

// 删除文件
const deleteFileFromList = async (fileId) => {
  try {
    await FileApi.deleteFile(fileId)
    message.success('删除成功')
    getFileList()
  } catch (error) {
    message.error('删除失败')
  }
}

// 显示添加分组弹窗
const showAddClassifyDialog = () => {
  isEditClassify.value = false
  classifyForm.value = { id: null, name: '' }
  classifyDialogVisible.value = true
}

// 编辑分组
const editClassify = (classify) => {
  isEditClassify.value = true
  classifyForm.value = { id: classify.id, name: classify.name }
  classifyDialogVisible.value = true
}

// 删除分组
const deleteClassify = async (classifyId) => {
  try {
    await ElMessageBox.confirm('确定要删除这个分组吗？', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })

    await FileClassifyApi.deleteFileClassify(classifyId)
    message.success('删除成功')
    getClassifyList()

    // 如果删除的是当前选中的分组，切换到全部
    if (currentClassifyId.value === classifyId) {
      selectClassify(null, '全部')
    }
  } catch (error) {
    if (error !== 'cancel') {
      message.error('删除失败')
    }
  }
}

// 确认分组操作（添加或编辑）
const confirmClassifyAction = async () => {
  if (!classifyForm.value.name.trim()) {
    message.warning('请输入分组名称')
    return
  }

  try {
    if (isEditClassify.value) {
      await FileClassifyApi.updateFileClassify(classifyForm.value)
      message.success('编辑分组成功')
    } else {
      await FileClassifyApi.createFileClassify({ name: classifyForm.value.name })
      message.success('添加分组成功')
    }

    classifyDialogVisible.value = false
    getClassifyList()
  } catch (error) {
    message.error(isEditClassify.value ? '编辑分组失败' : '添加分组失败')
  }
}

// 弹窗中的上传请求
const httpRequestForDialog = async (options) => {
  try {
    // 构建上传数据，包含分组ID
    const uploadData = {
      file: options.file,
      directory: props.directory
    }

    // 如果选择了分组，添加分组ID
    if (currentClassifyId.value) {
      uploadData.classifyId = currentClassifyId.value
      console.log('上传文件到分组:', currentClassifyId.value, '分组名:', currentClassifyName.value)
    } else {
      console.log('上传文件到默认分组')
    }

    console.log('上传参数:', uploadData)

    // 直接调用文件上传API
    const result = await FileApi.updateFile(uploadData)

    if (result.code === 0) {
      return result
    } else {
      throw new Error(result.msg || '上传失败')
    }
  } catch (error) {
    console.error('上传失败:', error)
    throw error
  }
}

// 弹窗中的上传成功回调
const uploadSuccessForDialog = (res) => {
  message.success('上传成功')
  getFileList()
}
</script>
<style lang="scss" scoped>
.is-error {
  .upload-wrapper {
    border: 1px dashed var(--el-color-danger) !important;

    &:hover {
      border-color: var(--el-color-primary) !important;
    }
  }
}

.disabled {
  .upload-wrapper {
    cursor: not-allowed !important;
    background: var(--el-disabled-bg-color);
    border: 1px dashed var(--el-border-color-darker) !important;

    &:hover {
      border: 1px dashed var(--el-border-color-darker) !important;
    }
  }
}

.upload-box {
  .no-border {
    .upload-wrapper {
      border: none !important;
    }
  }

  .upload-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: v-bind(width);
    height: v-bind(height);
    overflow: hidden;
    border: 1px dashed var(--el-border-color-darker);
    border-radius: v-bind(borderradius);
    transition: var(--el-transition-duration-fast);
    cursor: pointer;

    &:hover {
      border-color: var(--el-color-primary);

      .upload-handle {
        opacity: 1;
      }
    }

    .upload-image {
      width: 100%;
      height: 100%;
      object-fit: contain;
    }

    .upload-empty {
      position: relative;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      font-size: 12px;
      line-height: 30px;
      color: var(--el-color-info);

      .el-icon {
        font-size: 28px;
        color: var(--el-text-color-secondary);
      }
    }

    .upload-handle {
      position: absolute;
      top: 0;
      right: 0;
      display: flex;
      width: 100%;
      height: 100%;
      cursor: pointer;
      background: rgb(0 0 0 / 60%);
      opacity: 0;
      box-sizing: border-box;
      transition: var(--el-transition-duration-fast);
      align-items: center;
      justify-content: center;

      .handle-icon {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 0 6%;
        color: aliceblue;

        .el-icon {
          margin-bottom: 40%;
          font-size: 130%;
          line-height: 130%;
        }

        span {
          font-size: 85%;
          line-height: 85%;
        }
      }
    }
  }

  .el-upload__tip {
    line-height: 18px;
    text-align: center;
  }
}

/* 文件选择弹窗样式 */
.file-selector-dialog {
  .el-dialog__body {
    padding: 0;
  }
}

.file-selector-container {
  display: flex;
  height: 70vh;
  min-height: 500px;
}

/* 左侧分组栏 */
.classify-sidebar {
  width: 200px;
  background: #f8f9fa;
  border-right: 1px solid var(--el-border-color);
  display: flex;
  flex-direction: column;
}

.classify-list {
  flex: 1;
  padding: 16px 0;
  overflow-y: auto;
}

.classify-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  cursor: pointer;
  transition: all 0.3s;
  font-size: 14px;
  position: relative;

  &:hover {
    background: var(--el-fill-color-light);
  }

  &.active {
    background: var(--el-color-primary-light-9);
    color: var(--el-color-primary);
    border-right: 2px solid var(--el-color-primary);
  }

  .classify-actions {
    margin-left: auto;
    opacity: 0;
    transition: opacity 0.3s;
  }

  &:hover .classify-actions {
    opacity: 1;
  }
}

.add-classify-btn {
  padding: 5px;
  border-top: 1px solid var(--el-border-color);
}

/* 右侧内容区 */
.file-content-section {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 2px 20px;
  border-bottom: 1px solid var(--el-border-color);
  background: #fff;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  color: var(--el-text-color-regular);
}

.file-grid-container {
  flex: 1;
  padding: 20px;
  overflow-y: auto;
}

.file-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 16px;
  margin-bottom: 20px;
}

.file-item {
  cursor: pointer;
  transition: all 0.3s;
  border-radius: 8px;
  overflow: hidden;
  background: #fff;
  border: 2px solid transparent;

  &:hover {
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  }

  &.selected {
    border-color: var(--el-color-primary);
  }
}

.file-preview {
  position: relative;
  width: 100%;
  height: 120px;
  overflow: hidden;
  background: #f5f5f5;
}

.file-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.file-icon {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--el-fill-color-light);
}

.selected-mark {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 20px;
  height: 20px;
  background: var(--el-color-primary);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 12px;
}

.file-actions {
  position: absolute;
  top: 8px;
  right: 8px;
  opacity: 0;
  transition: opacity 0.3s;
}

.file-item:hover .file-actions {
  opacity: 1;
}

.file-name {
  padding: 8px;
  font-size: 12px;
  text-align: center;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--el-text-color-regular);
}

.bottom-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 5px;
  border-top: 1px solid var(--el-border-color);
  background: #fff;
}

.file-stats {
  font-size: 14px;
  color: var(--el-text-color-regular);
}



.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}
</style>
